mod error;
mod symbol_table;
mod type_checker;

use std::collections::BTreeMap;

use crate::ast_define::{MetaInfo, Program};

pub use error::{SemanticError, SemanticErrorType};
pub use symbol_table::{Symbol, SymbolTable, SymbolType, Type};
pub use type_checker::TypeChecker;

/// 语义分析入口函数
///
/// 根据lab3要求：
/// - 对于存在语义错误的输入，以标准错误输出打印语义错误信息
/// - 对于不存在语义错误的输入，输出 "No semantic errors in the program!"
pub fn analyze_program(program: &Program) {
    let mut type_checker = TypeChecker::new();

    match type_checker.analyze_program(program) {
        Ok(_) => print!("No semantic errors in the program!"),
        Err(errors) => {
            // 按行号排序错误，确保输出顺序一致
            // 若行内仅有一种错误, 那么就全部输出
            // 若行内有多于一种错误, 那么就仅输出第一种
            let mut sorted_errors = errors;
            sorted_errors.sort_by_key(|error| error.location.line);

            let mut last_line = 0;
            let mut last_error_type = None;

            for error in sorted_errors {
                // 当行数与上一个错误行数相同
                if error.location.line == last_line {
                    // 且错误类型也与之相同
                    if let Some(last_error_type) = last_error_type
                        && error.error_type == last_error_type
                    {
                        // 才输出
                        println!(
                            "Error type {} at Line {}: {}",
                            error.error_type as u8, error.location.line, error.message
                        );
                    } else {
                        // 行数相同但类型不同, 就跳过
                        continue;
                    }
                } else {
                    // 行数不同, 就输出
                    println!(
                        "Error type {} at Line {}: {}",
                        error.error_type as u8, error.location.line, error.message
                    );
                    // 更新行和错误类型
                    last_line = error.location.line;
                    last_error_type = Some(error.error_type);
                }
            }
        }
    }
}
